/**
 * <p>Title: MaterialCodeSvcImpl</p>
 * <p>Description: MaterialCodeSvc接口的实现类</p>
 * <p>Copyright: Shanghai Batchsight Pharmaceutical Technologies, Inc. Copyright(c) 2016</p>
 * @author Chen Wei
 * @version 1.0
 * <pre>Histroy:
 *       2016-11-22  Chen Wei
 *</pre>
*/
package cn.jhg.account.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import cn.jhg.account.persist.MaterialCodePropertyDao;
import cn.jhg.account.entity.AuditTrailObject;
import cn.jhg.account.entity.AuditTrailRecord;
import cn.jhg.account.entity.AuditTrailType;
import cn.jhg.account.entity.MaterialCode;
import cn.jhg.account.persist.MaterialCodeDao;
import cn.jhg.account.service.AuditTrailSvc;
import cn.jhg.account.util.SequenceProducer;
import cn.jhg.account.util.ServiceResult;
import cn.jhg.account.util.SymbolChange;
@Transactional
@Service("materialCodeSvc")
public class MaterialCodeSvcImpl implements MaterialCodeSvc{
	
	@Resource
	private MaterialCodeDao materialCodeDao;
	@Resource
	private MaterialCodePropertyDao materialCodePropertyDao;
	@Resource
	private SequenceProducer sequenceProducer;
	@Resource
	private AuditTrailSvc auditTrailSvc;
	Logger logger=LoggerFactory.getLogger(MaterialCodeSvcImpl.class);
	
	/**
	 * 添加原料编码
	 * @param code	编码
	 * @param sid	签名id
	 * @param iuid	调用人id
	 * @return		编码id，ErrorCode
	 */
	@Override
	public ServiceResult<Integer> addCode(MaterialCode code, int sid, int iuid) {
		ServiceResult<Integer> result=new ServiceResult<Integer>();
		String c=code.getCode();
		try{
			MaterialCode materialCode=materialCodeDao.queryByCode(c);
			if(materialCode!=null){
				result.setErrorCode(223032378);//此原料编号已存在
				logger.error("[ERR223032378] 此原料编号已存在");
			}else{
				int id=sequenceProducer.nextval("t_ibcp_material_code");
				code.setId(id);
				ObjectId objId=new ObjectId();//创建一个新的objId
				code.setPropId(objId.toHexString());
				materialCodePropertyDao.addCodeProperty(objId,code.getProperty());//调用mongoDB添加方法
				materialCodeDao.addCode(code);//添加到mysql数据库中
				result.setErrorCode(0);
				result.setData(id);
				logger.info("[INF223032381] 添加原料编码成功");
				
				// 添加审计追踪记录
				AuditTrailRecord atRecord = new AuditTrailRecord();
				atRecord.setSid(sid); // 签名 id
				atRecord.setUid(iuid); // 用户 id
				atRecord.setLid(100);
				atRecord.setTid(AuditTrailType.AddCode.GetId()); // 审计追踪类型 id
				atRecord.setOtid(AuditTrailObject.MaterialCode.getId());    // 审计追踪对象 id
				
				Document metadata = new Document(); // 审计追踪元数据
				metadata.append("MaterialCodeId",code.getId());
				metadata.append("MaterialCodeCode",code.getCode());
				metadata.append("MaterialCodeName",code.getName());
				metadata.append("MaterialCodeValid",code.getValid());
				atRecord.setMeta(metadata);
				auditTrailSvc.addRecord(atRecord);
			}//else 语句结束			
			return result;
		}catch(Exception e){
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032397);
			logger.error("[ERR223032397] 添加原料编码失败！" + e.getMessage());
			return result;
		}
	}
	/**
	 * 更新原料编码
	 * @param code	原料代码
	 * @param sid	签名id
	 * @param iuid	调用者id
	 * @return		ErrorCode
	 */
	@Override
	public ServiceResult<Integer> updateCode(MaterialCode code, int sid, int iuid) {
		ServiceResult<Integer> result=new ServiceResult<Integer>();
		String c=code.getCode();
		try{
			MaterialCode materialCode=materialCodeDao.queryByCode(c);
			if(materialCode!=null&&code.getId()!=materialCode.getId()){
				result.setErrorCode(223032410);
				logger.error("[ERR223032410] 此原料编号已经存在");
			}else{
				ObjectId propId=new ObjectId(code.getPropId());//获取propId
				materialCodePropertyDao.updateCodeProperty(propId,code.getProperty());
				materialCodeDao.updateCode(code);
				result.setErrorCode(0);
				logger.info("[INF223032433] 修改原料编码成功");
				
				// 添加审计追踪记录
				AuditTrailRecord atRecord = new AuditTrailRecord();
				atRecord.setSid(sid); // 签名 id
				atRecord.setUid(iuid); // 用户 id
				atRecord.setLid(100);
				atRecord.setTid(AuditTrailType.UpdateCode.GetId()); // 审计追踪类型 id
				atRecord.setOtid(AuditTrailObject.MaterialCode.getId());    // 审计追踪对象 id

				Document metadata = new Document(); // 审计追踪元数据
				metadata.append("MaterialCodeId",code.getId());
				metadata.append("MaterialCodeCode",code.getCode());
				metadata.append("MaterialCodeName",code.getName());
				metadata.append("MaterialCodeValid",code.getValid());
				atRecord.setMeta(metadata);
				auditTrailSvc.addRecord(atRecord);
			}//else 语句结束			
			return result;
		}catch(Exception e){//try语句结束
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032452);
			logger.error("[ERR223032452] 修改原料编码失败！" + e.getMessage());
			return result;
		}
	}

	/**
	 * 根据代码查询
	 * @param code	编码
	 * @param iuid	调用者 id
	 * @return		MaterialCode 实体，ErrorCode
	 */
	@Override
	public ServiceResult<MaterialCode> queryByCode(String code, int iuid) {
		ServiceResult<MaterialCode> result=new ServiceResult<MaterialCode>();
		try {
			MaterialCode materialCode=materialCodeDao.queryByCode(code);
			ObjectId propId=new ObjectId(materialCode.getPropId());//获取propId
			System.out.println(propId);
			Document property=materialCodePropertyDao.getCodePropertyByPropId(propId);//调用getCodePropertyByPropId
			materialCode.setProperty(property);
			result.setErrorCode(0);// 查询成功
			result.setData(materialCode);
			logger.info("[INF223032495] queryByCode查询成功！");
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032510);
			logger.error("[ERR223032510] 根据Code查询原料编码失败", e.getMessage());
			return result;
		}
	}
	
	/**
	 * 根据 ID 查询
	 * @param id	编码id
	 * @param iuid	调用者id
	 * @return		MaterialCode 实体， ErrorCode
	 */
	@Override
	public ServiceResult<MaterialCode> queryById(int id, int iuid) {
		ServiceResult<MaterialCode> result=new ServiceResult<MaterialCode>();
		try {
			MaterialCode materialCode=materialCodeDao.queryById(id);
			ObjectId propId=new ObjectId(materialCode.getPropId());//获取propId
			System.out.println(propId);
			Document property=materialCodePropertyDao.getCodePropertyByPropId(propId);//调用getCodePropertyByPropId
			materialCode.setProperty(property);
			result.setErrorCode(0);// 查询成功
			result.setData(materialCode);
			logger.info("[INF223032533] queryById查询成功！");
			
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032545);
			logger.error("[ERR223032545] 根据ID查询原料编码失败", e.getMessage());
			return result;
		}
	}
	
	/**
	 * 查询原料代码
	 * @param code		编码
	 * @param name		原料编码名称
	 * @param spec		原料规格
	 * @param typeId	原料类型 id
	 * @param iuid		调用者id
	 * @return			符合条件的原料编码 id 集合，ErrorCode
	 */
	@Override
	public ServiceResult<List<Integer>> findCode(String code, String name, String spec, int typeId, int iuid) {
		ServiceResult<List<Integer>> result = new ServiceResult<List<Integer>>();
		code = "%" + code + "%";
		name = "%" + name + "%";
		spec = "%" + spec + "%";
		MaterialCode materialCode=new MaterialCode();
		materialCode.setCode(code);;
		materialCode.setName(name);
		materialCode.setSpec(spec);
		materialCode.setTypeId(typeId);
		try {
			List<Integer> list=materialCodeDao.findCode(materialCode);
			if (list == null) {
				result.setErrorCode(223032555);// 没有查询到符合条件的原料编码
				logger.error("[ERR223032555] 没有查询到符合条件的原料编码");
			} else {
				result.setErrorCode(0);// 查询原料编码成功
				result.setData(list);
				logger.info("[INF223032569] findCode查询成功！");
			}
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032580);
			logger.error("[ERR223032580] 多条件查询原料编码失败", e.getMessage());
			return result;
		}
	}
	/**
	 * 查询原料代码
	 * @param code		编码
	 * @param name		原料编码名称
	 * @param spec		原料规格
	 * @param typeId	原料类型 id
	 * @param iuid		调用者id
	 * @return			符合条件的原料编码实体集合，ErrorCode
	 */
	@Override
	public ServiceResult<List<MaterialCode>> findCodeDetail(String code, String name, String spec, int typeId, int iuid) {
		ServiceResult<List<MaterialCode>> result = new ServiceResult<List<MaterialCode>>();
		code = "%" + code + "%";
		name = "%" + name + "%";
		spec = "%" + spec + "%";
		MaterialCode materialCode=new MaterialCode();
		materialCode.setCode(code);;
		materialCode.setName(name);
		materialCode.setSpec(spec);
		materialCode.setTypeId(typeId);
		try {
			List<MaterialCode> list=materialCodeDao.findCodeDetail(materialCode);
			result.setErrorCode(0);// 查询原料编码成功
			result.setData(list);
			logger.info("[INF223032602] findCodeDetail查询成功！");
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032610);
			logger.error("[ERR223032610] 多条件查询原料编码失败", e.getMessage());
			return result;
		}
	}
	/**
	 * 失效原料编码
	 * @param id	原料编码id
	 * @param sid	签名id
	 * @param iuid	调用者id
	 * @return		ErrorCode
	 */
	@Override
	public ServiceResult<Integer> invalidCode(int id, int sid, int iuid) {
		ServiceResult<Integer> result=new ServiceResult<Integer>();
		try {
			MaterialCode materialCode=materialCodeDao.queryById(id);
			if (materialCode.getValid()==false) {
				result.setErrorCode(223032618);// 此id的原料编码valid为已失效状态
				logger.error("[ERR223032618] 此id的原料编码valid为已失效状态");
			} else {
				materialCodeDao.invalidCode(id);
				result.setErrorCode(0);// 失效原料编码成功
				logger.info("[INF223032630] invalidCode失效原料编码成功！");
				
				// 添加审计追踪记录
				AuditTrailRecord atRecord = new AuditTrailRecord();
				atRecord.setSid(sid); // 签名 id
				atRecord.setUid(iuid); // 用户 id
				atRecord.setLid(100);
				atRecord.setTid(AuditTrailType.InvalidCode.GetId()); // 审计追踪类型 id
				atRecord.setOtid(AuditTrailObject.MaterialCode.getId());    // 审计追踪对象 id
				
				Document metadata = new Document(); // 审计追踪元数据
				metadata.append("MaterialCodeId",materialCode.getId());
				metadata.append("MaterialCodeCode",materialCode.getCode());
				metadata.append("MaterialCodeName",materialCode.getName());
				metadata.append("MaterialCodeValid",materialCode.getValid());
				atRecord.setMeta(metadata);
				auditTrailSvc.addRecord(atRecord);
			}
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032642);
			logger.error("[ERR223032642] 失效原料编码失败",  e.getMessage());
			return result;
		}
	}
	/**
	 * 
	 * @param id	删除原料编码
	 * @param sid	签名 id
	 * @param iuid	调用者 id
	 * @return		ErrorCode
	 */
	@Override
	public ServiceResult<Integer> deleteCode(int id, int sid, int iuid) {
		ServiceResult<Integer> result=new ServiceResult<Integer>();
		try {
			MaterialCode materialCode=materialCodeDao.queryById(id);
			ObjectId propId=new ObjectId(materialCode.getPropId());//获取propId
			materialCodePropertyDao.deleteCodeProperty(propId);//调用deleteCodeProperty
			materialCodeDao.deleteCode(id);
			result.setErrorCode(0);// 删除原料编码成功
			logger.info("[INF223032667] deleteCode删除原料编码成功！");
			
			// 添加审计追踪记录
			AuditTrailRecord atRecord = new AuditTrailRecord();
			atRecord.setSid(sid); // 签名 id
			atRecord.setUid(iuid); // 用户 id
			atRecord.setLid(100);
			atRecord.setTid(AuditTrailType.DeleteCode.GetId()); // 审计追踪类型 id
			atRecord.setOtid(AuditTrailObject.MaterialCode.getId());    // 审计追踪对象 id
			
			Document metadata = new Document(); // 审计追踪元数据
			metadata.append("MaterialCodeId",materialCode.getId());
			metadata.append("MaterialCodeCode",materialCode.getCode());
			metadata.append("MaterialCodeName",materialCode.getName());
			metadata.append("MaterialCodeValid",materialCode.getValid());
			atRecord.setMeta(metadata);
			auditTrailSvc.addRecord(atRecord);
			return result;
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(223032675);
			logger.error("[ERR223032675] 删除原料编码失败",  e.getMessage());
			return result;
		}
	}
	

	/**
	 * 查询原料详细信息
	 * @param typeId 原料类型id
	 * @param str  包含code 原料编码 和 name 原料名称
	 * @return	ServiceResult<List<MaterialCode>> 	原料实体集合，ErrorCode
	 */
	@Override
	public ServiceResult<List<MaterialCode>> findMaterialCodeDetail(int typeId, String str) {
		ServiceResult<List<MaterialCode>> result = new ServiceResult<List<MaterialCode>>();
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			List<MaterialCode> list = new ArrayList<MaterialCode>();
			str=str.trim();
			if(str.trim().contains(" ")||str.trim().contains(",")||str.trim().contains("，")){ //将字符串中符号转换成" "
				String strChange = SymbolChange.Symbol(str);
				String[] s = strChange.split(" ");
				for(int i=0 ; i<s.length ; i++){
					map.put("typeId", typeId);
					String name = "%"+s[i]+"%";
					String code = "%"+s[i]+"%";
					map.put("name", name);
					map.put("code", code);
					list = materialCodeDao.findMaterialCodeDetail(map);
				}				
			}else{
				map.put("typeId", typeId);
				String name = "%"+str+"%";
				String code = "%"+str+"%";
				map.put("name", name);
				map.put("code", code);
				list = materialCodeDao.findMaterialCodeDetail(map);
			}
			result.setData(list);
			result.setErrorCode(0);
			logger.info("[INF226288160] 查询原料编码详细信息成功");
			return result;
		} catch (Exception e) {//try 语句结束
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(226315456);
			logger.error("[ERR226315456] 查询原料编码详细信息失败", e.getMessage());
			return result;
		}
	}
	
	/**
	 * 查询原料详细信息
	 * @param  str  包含code 原料编码 和 name 原料名称
	 * @return	ServiceResult<List<MaterialCode>> 	原料实体集合，ErrorCode
	 */
	@Override
	public ServiceResult<List<MaterialCode>> findMaterialCodeDetails(String str) {
		ServiceResult<List<MaterialCode>> result = new ServiceResult<List<MaterialCode>>();
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			List<MaterialCode> list = new ArrayList<MaterialCode>();
			str=str.trim();
			if(str.trim().contains(" ")||str.trim().contains(",")||str.trim().contains("，")){ //将字符串中符号转换成" "
				String strChange = SymbolChange.Symbol(str);
				String[] s = strChange.split(" ");
				for(int i=0 ; i<s.length ; i++){
					String name = "%"+s[i]+"%";
					String code = "%"+s[i]+"%";
					map.put("name", name);
					map.put("code", code);
					list = materialCodeDao.findMaterialCodeDetails(map);
				}				
			}else{
				String name = "%"+str+"%";
				String code = "%"+str+"%";
				map.put("name", name);
				map.put("code", code);
				list = materialCodeDao.findMaterialCodeDetails(map);
			}
			result.setData(list);
			result.setErrorCode(0);
			logger.info("[INF230889413] 查询原料编码详细信息成功");
			return result;
		} catch (Exception e) {//try 语句结束
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			result.setErrorCode(230869400);
			logger.error("[ERR230869400] 查询原料编码详细信息失败", e.getMessage());
			return result;
		}
	}

}
